Add error checking for flagrantly malformed xcsv files.
authorrobertlipe <robertlipe@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Wed, 17 Sep 2014 05:15:44 +0000 (05:15 +0000)
committerrobertlipe <robertlipe@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Wed, 17 Sep 2014 05:15:44 +0000 (05:15 +0000)
Tested: ./testo on Mac.

gpsbabel/csv_util.cc
gpsbabel/gbfile.cc
gpsbabel/gbfile.h

index f5a1f69f02f9bdb5d6306aac720f95e427028d8b..311d1a362e84983cb7ad2a61545861934467f347 100644 (file)
 #include <math.h>
 #include <stdlib.h>
 #include <QtCore/QRegExp>
+
 #include "defs.h"
 #include "csv_util.h"
+#include "garmin_fs.h"
 #include "grtcirc.h"
-#include "strptime.h"
 #include "jeeps/gpsmath.h"
-#include "garmin_fs.h"
+#include "src/core/logging.h"
+#include "strptime.h"
 
 #define MYNAME "CSV_UTIL"
 
@@ -175,15 +177,6 @@ static UrlLink* link_;
 /*     usage: p = csv_stringclean(stringtoclean, "&,\"")             */
 /*            (strip out ampersands, commas, and quotes.             */
 /*********************************************************************/
-// Implement the C version via Qt - the reverse of most of our shims.
-char*
-csv_stringclean(const char* source, const char* chararray)
-{
-  /* Make a copy of the source... */
-  QString cleansed(csv_stringclean(QString(source), chararray));
-  return xstrdup(cleansed);
-}
-
 QString
 csv_stringclean(const QString& source, const QString& to_nuke)
 {
@@ -749,6 +742,23 @@ xcsv_file_init(void)
   xcsv_file.gps_datum = GPS_DATUM_WGS84;
 }
 
+void validate_fieldmap(field_map_t* fmp, bool is_output) {
+  QString qkey = fmp->key;
+  QString qval = fmp->val;
+  QString qprintfc = fmp->printfc;
+
+  if (qkey.isEmpty()) {
+    Fatal() << MYNAME << ": xcsv style is missing" << 
+            (is_output ? "output" : "input") << "field type.";
+  }
+  if (!fmp->val) {
+    Fatal() << MYNAME << ": xcsv style" << qkey << "is missing default.";
+  }
+  if (is_output && !fmp->printfc) {
+    Fatal() << MYNAME << ": xcsv style" << qkey << "output is missing format specifier.";
+  }
+}
+
 /*****************************************************************************/
 /* xcsv_ifield_add() - add input field to ifield queue.                      */
 /* usage: xcsv_ifield_add("DESCRIPTION", "", "%s")                           */
@@ -763,6 +773,7 @@ xcsv_ifield_add(char* key, char* val, char* pfc)
   fmp->hashed_key = xm ? xm->xt_token : -1;
   fmp->val = val;
   fmp->printfc = pfc;
+  validate_fieldmap(fmp, false);
 
   ENQUEUE_TAIL(&xcsv_file.ifield, &fmp->Q);
   xcsv_file.ifield_ct++;
@@ -783,6 +794,7 @@ xcsv_ofield_add(char* key, char* val, char* pfc, int options)
   fmp->val = val;
   fmp->printfc = pfc;
   fmp->options = options;
+  validate_fieldmap(fmp, true);
 
   ENQUEUE_TAIL(xcsv_file.ofield, &fmp->Q);
   xcsv_file.ofield_ct++;
@@ -1598,7 +1610,6 @@ xcsv_waypt_pr(const Waypoint* wpt)
 
   i = 0;
   QUEUE_FOR_EACH(xcsv_file.ofield, elem, tmp) {
-    char* obuff;
     double lat = latitude;
     double lon = longitude;
     /*
@@ -1657,7 +1668,7 @@ xcsv_waypt_pr(const Waypoint* wpt)
         anyname = wpt->notes;
       }
       if (anyname.isEmpty()) {
-        anyname = xstrdup(fmp->val);
+        anyname = fmp->val;
       }
       buff = QString().sprintf(fmp->printfc, CSTR(anyname));
       }
@@ -2113,10 +2124,10 @@ xcsv_waypt_pr(const Waypoint* wpt)
       warning(MYNAME ": Unknown style directive: %s\n", fmp->key);
       break;
     }
-    obuff = csv_stringclean(CSTR(buff), xcsv_file.badchars);
+    QString obuff = csv_stringclean(buff, xcsv_file.badchars);
 
     if (field_is_unknown && fmp->options & OPTIONS_OPTIONAL) {
-      goto next;
+      continue;
     }
 
     if (xcsv_file.field_encloser) {
@@ -2128,18 +2139,14 @@ xcsv_waypt_pr(const Waypoint* wpt)
      * ""%s"" to smuggle bad characters through.
      */
     if (0 == strcmp(fmp->printfc, "\"%s\"")) {
-      gbfprintf(xcsv_file.xcsvfp, "\"%s\"", obuff);
-    } else {
-      gbfprintf(xcsv_file.xcsvfp, "%s", obuff);
+      obuff = '"' + obuff + '"';
     }
+    gbfputs(obuff, xcsv_file.xcsvfp);
 
     if (xcsv_file.field_encloser) {
       /* print the enclosing character(s) */
       gbfprintf(xcsv_file.xcsvfp, "%s", xcsv_file.field_encloser);
     }
-
-next:
-    xfree(obuff);
   }
 
   gbfprintf(xcsv_file.xcsvfp, "%s", xcsv_file.record_delimiter);
index c6d5c9d443b86a1ba5e5e8dc735aa60983ba6b23..fb1462ecb79c505935924ee88b3059a39bcf353c 100644 (file)
@@ -776,12 +776,6 @@ gbfputc(int c, gbfile* file)
  * gbfputs: (as fputs)
  */
 
-int
-gbfputs(const char* s, gbfile* file)
-{
-  return gbfwrite(s, 1, strlen(s), file);
-}
-
 // This is a depressing hack, meant to ease the pain from C strings
 // to QStrings, which are consitently encoded.
 int
@@ -1228,24 +1222,13 @@ gbfputflt(const float f, gbfile* file)
  * gbfputcstr: write a NULL terminated string into a stream (!) including NULL
  *             return the number of written characters
  */
-
 int
-gbfputcstr(const char* s, gbfile* file)
+gbfputcstr(const QString& s, gbfile* file) 
 {
-  int len;
-
-  len = (s == NULL) ? 0 : strlen(s);
-  if (len > 0) {
-    return gbfwrite(s, 1, len + 1, file);
-  } else {
-    gbfputc(0, file);
-    return 1;
-  }
-}
-int
-gbfputcstr(const QString& s, gbfile* file)
-{
-  return gbfputcstr(qPrintable(s), file);
+  QByteArray qs = s.toUtf8();
+  int rv =  gbfwrite(qs.constData(), 1, qs.size(), file);
+  gbfputc(0, file);
+  return rv;
 }
 
 /*
@@ -1253,29 +1236,17 @@ gbfputcstr(const QString& s, gbfile* file)
  *             return the number of written characters
  */
 
-int
-gbfputpstr(const char* s, gbfile* file)
-{
-  int len;
-
-  len = (s == NULL) ? 0 : strlen(s);
-  if (len > 255) {
-    len = 255;  /* the maximum size of a standard pascal string */
-  }
-  gbfputc(len, file);
-  if (len > 0) {
-    gbfwrite(s, 1, len, file);
-  }
-  return (len + 1);
-}
-
 int
 gbfputpstr(const QString& s, gbfile* file)
 {
-  const char* t = xstrdup(CSTR(s));
-  int r = gbfputpstr(t, file);
-  xfree(t);
-  return r;
+  QString out(s);
+  // Pascal strings can be a max of 255 bytes.
+  out.truncate(255);
+
+  gbfputc(out.size(), file);
+  QByteArray qs = s.toUtf8();
+  int rv =  gbfwrite(qs.constData(), 1, qs.size(), file);
+  return rv;
 }
 
 /* Much more higher level functions */
index 7cf0c726a6585244b41a1106ea4eba3072e30cb4..2aa17d3bdc82306a33184b5f895dc56ec43eca7e 100644 (file)
@@ -100,7 +100,6 @@ QString gbfgets(char* buf, int len, gbfile* file);
 int gbvfprintf(gbfile* file, const char* format, va_list ap);
 int gbfprintf(gbfile* file, const char* format, ...);
 int gbfputc(int c, gbfile* file);
-int gbfputs(const char* s, gbfile* file);
 int gbfputs(const QString& s, gbfile* file);
 int gbfwrite(const void* buf, const gbsize_t size, const gbsize_t members, gbfile* file);
 int gbfflush(gbfile* file);
@@ -132,10 +131,8 @@ int gbfputint32(const int32_t i, gbfile* file);
 int gbfputdbl(const double d, gbfile* file);   // write a double value
 int gbfputflt(const float f, gbfile* file);    // write a float value
 
-int gbfputcstr(const char* s, gbfile* file);   // write string including '\0'
 int gbfputcstr(const QString& s, gbfile* file);        // write string including '\0'
 
-int gbfputpstr(const char* s, gbfile* file);   // write as pascal string
 int gbfputpstr(const QString& s, gbfile* file);        // write as pascal string
 
 gbsize_t gbfcopyfrom(gbfile* file, gbfile* src, gbsize_t count);